﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;

class HotUpdate:MonoBehaviour
{
    byte[] m_ReadPathFileListData;
    byte[] m_ServerFileListData;
    private void Start()
    {
        if (IsFirstInstall())
        {
            ReleaseResources();
        }
        else
        {
            CheckUndate();
        }
    }

    private void CheckUndate()
    {

        string url = Path.Combine(Appconst.ResourcesUrl, Appconst.FileListName);
        DownFileInfo info = new DownFileInfo();
        info.url = url;
        StartCoroutine( DownloadFile(info, OnDownloadServerFileListComplete));
    }

    private void OnDownloadServerFileListComplete(DownFileInfo file)
    {
        m_ServerFileListData = file.fileData.data;
        List<DownFileInfo> fileInfos = GetFileList(file.fileData.text, Appconst.ResourcesUrl);
        List<DownFileInfo> downFiles = new List<DownFileInfo>();
        foreach(var info in fileInfos)
        {
            string localFile = Path.Combine(PathUtil.ReadWritePath, info.fileName);
            if (!FileUtil.IsExists(localFile))
            {
                downFiles.Add(info);
            }
        }
        if (downFiles.Count == 0)
            EnterGame();
        else
            StartCoroutine(DownloadFile(downFiles, OnUpdateFileComplete, OnUpdateAllFileComplete));
    }

    private void OnUpdateAllFileComplete()
    {
        FileUtil.WriteFile(Path.Combine(PathUtil.ReadWritePath, Appconst.FileListName), m_ServerFileListData);
        EnterGame();
    }

    private void OnUpdateFileComplete(DownFileInfo file)
    {
        Debug.Log("服务器更新文件到可写目录："+file.url);
        FileUtil.WriteFile(Path.Combine(PathUtil.ReadWritePath, file.fileName), file.fileData.data);
    }

    private void ReleaseResources()
    {
        //这是只读目录的地址
        string url = Path.Combine(PathUtil.ReadPath, Appconst.FileListName);
        //这是只读目录中要释放文件的信息
        DownFileInfo info = new DownFileInfo();
        //先把地址传给要释放文件
        info.url = url;
        //注意只读目录第一个文件就是只读目录的其余文件列表，等待该次文件的数据传给了info，完成过执行OnDownloadReadPathFileListComplete
        StartCoroutine(DownloadFile(info, OnDownloadReadPathFileListComplete));
    }

    //拿到文件列表文件数据我们把他解析成可用的文件列表
    private void OnDownloadReadPathFileListComplete(DownFileInfo info)
    {
        m_ReadPathFileListData = info.fileData.data;
        //读取文件数据得出文件列表
        List<DownFileInfo> fileInfos = GetFileList(info.fileData.text, PathUtil.ReadPath);
        //开始下载所有文件
        StartCoroutine(DownloadFile(fileInfos, OnReleaseFileComplete, OnReleaseAllFileComplete));
    }


    //当所有文件下载成功后
    private void OnReleaseAllFileComplete()
    {
        FileUtil.WriteFile(Path.Combine(PathUtil.ReadWritePath, Appconst.FileListName), m_ReadPathFileListData);
        CheckUndate();
    }

    //当一个文件下载成功后
    private void OnReleaseFileComplete(DownFileInfo fileInfo)
    {
        Debug.Log("只读目录释放文件到可写目录：" + fileInfo.url);
        string writeFile = Path.Combine(PathUtil.ReadWritePath, fileInfo.fileName);
        FileUtil.WriteFile(writeFile, fileInfo.fileData.data);
    }

    private bool IsFirstInstall()
    {
        bool isExistsReadPath = FileUtil.IsExists(Path.Combine(PathUtil.ReadPath, Appconst.FileListName));
        bool isExistsReadWritePath = FileUtil.IsExists(Path.Combine(PathUtil.ReadWritePath, Appconst.FileListName));

        return isExistsReadPath && !isExistsReadWritePath;

    }

    internal class DownFileInfo
    {
        public string url;
        public string fileName;
        public DownloadHandler fileData;
    }

    /// <summary>
    /// 下载单个文件
    /// </summary>
    /// <param name="url"></param>
    /// <returns></returns>
    IEnumerator DownloadFile(DownFileInfo info,Action<DownFileInfo> Complete)
    {
        //发送下载请求
        UnityWebRequest webRequest = UnityWebRequest.Get(info.url);
        yield return webRequest.SendWebRequest();
        //如果请求失败
        if (webRequest.result == UnityWebRequest.Result.ConnectionError
            || webRequest.result == UnityWebRequest.Result.ProtocolError
            || webRequest.result == UnityWebRequest.Result.DataProcessingError)
        {
            Debug.LogError("下载文件出错：" + info.url);
            yield break;
        }
        //请求成功的话就把文件数据传给info并且执行请求成功后的函数
        info.fileData = webRequest.downloadHandler;
        Complete?.Invoke(info);
        //走之前把下载请求释放咯
        webRequest.Dispose();
    }
    /// <summary>
    /// 下载多个文件
    /// </summary>
    /// <param name="info"></param>
    /// <param name="Complete"></param>
    /// <returns></returns>
    IEnumerator DownloadFile(List<DownFileInfo> infos, Action<DownFileInfo> Complete, Action DownloadAllComplete)
    {
        foreach(DownFileInfo info in infos)
        {
            yield return DownloadFile(info, Complete);
        }
        DownloadAllComplete?.Invoke();
    }

    /// <summary>
    /// 获取文件信息
    /// </summary>
    /// <param name="fileData"></param>
    /// <returns></returns>
    private List<DownFileInfo> GetFileList(string fileData,string path)
    {
        string content = fileData.Trim().Replace("\r", "");
        string[] files = content.Split('\n');
        List<DownFileInfo> downFileInfos = new List<DownFileInfo>(files.Length);
        for(int i = 0; i < files.Length; i++)
        {
            string[] file = files[i].Split('|');
            DownFileInfo fileInfo= new DownFileInfo();
            fileInfo.fileName = file[1];
            fileInfo.url = Path.Combine(path, file[1]);
            downFileInfos.Add(fileInfo);
        }
        return downFileInfos;
    }

    /// <summary>
    /// 进入游戏
    /// </summary>
    private void EnterGame()
    {
        Manager.Resource.PraseVersionFile();
        Manager.Resource.LoadUI("TestUI", OnComplete);
    }

    private void OnComplete(UnityEngine.Object obj)
    {
        GameObject go = Instantiate(obj) as GameObject;
        go.transform.SetParent(this.transform);
        go.SetActive(true);
        go.transform.localPosition = Vector3.zero;
    }
}

